﻿
#include "EMath.h"
#include "EVector.h"
#include "EMatrix.h"
#include "ECore.h"

namespace Base3D
{
	//--------------------------------------------------------------------------

	// 获取平移变换矩阵
	void GetTranslateMatrix44(EMatrix44 &mat, EFloat x, EFloat y, EFloat z)
	{
		mat.m[0][0] = 1, mat.m[0][1] = 0, mat.m[0][2] = 0, mat.m[0][3] = 0;
		mat.m[1][0] = 0, mat.m[1][1] = 1, mat.m[1][2] = 0, mat.m[1][3] = 0;
		mat.m[2][0] = 0, mat.m[2][1] = 0, mat.m[2][2] = 1, mat.m[2][3] = 0,
		mat.m[3][0] = x, mat.m[3][1] = y, mat.m[3][2] = z, mat.m[3][3] = 1;
	}

	//--------------------------------------------------------------------------

	// 获取缩放变换矩阵
	void GetScaleMatrix44(EMatrix44 &mat, EFloat x, EFloat y, EFloat z)
	{
		//return EMatrix44(x, 0, 0, 0,
		//				0, y, 0, 0,
		//				0, 0, z, 0,
		//				0, 0, 0, 1);

		mat.m[0][0] = x, mat.m[0][1] = 0, mat.m[0][2] = 0, mat.m[0][3] = 0;
		mat.m[1][0] = 0, mat.m[1][1] = y, mat.m[1][2] = 0, mat.m[1][3] = 0;
		mat.m[2][0] = 0, mat.m[2][1] = 0, mat.m[2][2] = z, mat.m[2][3] = 0,
		mat.m[3][0] = 0, mat.m[3][1] = 0, mat.m[3][2] = 0, mat.m[3][3] = 1;
	}

	//--------------------------------------------------------------------------

	// 获取延X轴旋转变换矩阵
	// 旋转参数为角度, 非弧度
	void GetRotateMatrix44Z(EMatrix44 &mat, EFloat degree)
	{
		EFloat sinA = sin(Degree_TO_Radian(degree));
		EFloat cosA = cos(Degree_TO_Radian(degree));

		//return EMatrix44(cosA, sinA,	0,	0,
		//				-sinA, cosA,	0,	0,
		//				0,		0,		1,	0,
		//				0,		0,		0,	1);

		mat.m[0][0] = cosA,		mat.m[0][1] = sinA, mat.m[0][2] = 0, mat.m[0][3] = 0;
		mat.m[1][0] = -sinA,	mat.m[1][1] = cosA, mat.m[1][2] = 0, mat.m[1][3] = 0;
		mat.m[2][0] = 0,		mat.m[2][1] = 0,	mat.m[2][2] = 1, mat.m[2][3] = 0,
		mat.m[3][0] = 0,		mat.m[3][1] = 0,	mat.m[3][2] = 0, mat.m[3][3] = 1;
	}

	//--------------------------------------------------------------------------

	// 获取延Y轴旋转变换矩阵
	// 旋转参数为角度, 非弧度
	void GetRotateMatrix44X(EMatrix44 &mat, EFloat degree)
	{
		EFloat sinA = sin(Degree_TO_Radian(degree));
		EFloat cosA = cos(Degree_TO_Radian(degree));

		//return EMatrix44(1,		0,		0,		0,
		//				0,		cosA,	sinA,	0,
		//				0,		-sinA,	cosA,	0,
		//				0,		0,		0,		1);

		mat.m[0][0] = 1, mat.m[0][1] = 0,		mat.m[0][2] = 0,	mat.m[0][3] = 0;
		mat.m[1][0] = 0, mat.m[1][1] = cosA,	mat.m[1][2] = sinA, mat.m[1][3] = 0;
		mat.m[2][0] = 0, mat.m[2][1] = -sinA,	mat.m[2][2] = cosA, mat.m[2][3] = 0,
		mat.m[3][0] = 0, mat.m[3][1] = 0,		mat.m[3][2] = 0,	mat.m[3][3] = 1;
	}

	//--------------------------------------------------------------------------

	// 获取延Z轴旋转变换矩阵
	// 旋转参数为角度, 非弧度
	void GetRotateMatrix44Y(EMatrix44 &mat, EFloat degree)
	{
		EFloat sinA = sin(Degree_TO_Radian(degree));
		EFloat cosA = cos(Degree_TO_Radian(degree));

		//return EMatrix44(cosA,  0,		-sinA,	0,
		//				0,		1,		0,		0,
		//				sinA,	0,		cosA,	0,
		//				0,		0,		0,		1);

		mat.m[0][0] = cosA, mat.m[0][1] = 0, mat.m[0][2] = -sinA,	mat.m[0][3] = 0;
		mat.m[1][0] = 0,	mat.m[1][1] = 1, mat.m[1][2] = 0,		mat.m[1][3] = 0;
		mat.m[2][0] = sinA, mat.m[2][1] = 0, mat.m[2][2] = cosA,	mat.m[2][3] = 0,
		mat.m[3][0] = 0,	mat.m[3][1] = 0, mat.m[3][2] = 0,		mat.m[3][3] = 1;
	}

	//--------------------------------------------------------------------------

	void GetRotateMatrix44(EMatrix44 &mat, const EVector4D &n, EFloat degree)
	{
		EFloat sinA = sin(Degree_TO_Radian(degree));
		EFloat cosA = cos(Degree_TO_Radian(degree));

		EFloat oneCosA = 1 - cosA;

		// nx * nx * (1- cosA) + cosA		nx * ny *(1 - cosA) + nx * sinA		nx * nz *(1 - cosA) - ny * sinA
		// nx * ny * (1- cosA) - nz * sinA	ny * ny *(1 - cosA) + cosA			nx * nz *(1 - cosA) + nx * sinA
		// nx * nz * (1- cosA) + ny * sinA	ny * nz *(1 - cosA) - nx * sinA		nz * nz *(1 - cosA) + cosA

		mat.m[0][0] = n.x * n.x * oneCosA + cosA,			mat.m[0][1] = n.x * n.y * oneCosA + n.x * sinA,		mat.m[0][2] = n.x * n.z * oneCosA - n.y * sinA,		mat.m[0][3] = 0;
		mat.m[1][0] = n.x * n.y * oneCosA - n.z * sinA,		mat.m[1][1] = n.y * n.y * oneCosA + cosA,			mat.m[1][2] = n.y * n.z * oneCosA + n.x * sinA,		mat.m[1][3] = 0;
		mat.m[2][0] = n.x * n.z * oneCosA + n.y * sinA,		mat.m[2][1] = n.y * n.z * oneCosA - n.x * sinA,		mat.m[2][2] = n.z * n.z * oneCosA + cosA,			mat.m[2][3] = 0,
		mat.m[3][0] = 0,									mat.m[3][1] = 0,									mat.m[3][2] = 0,									mat.m[3][3] = 1;
	}

	//--------------------------------------------------------------------------

	// 3D向量X44矩阵
	void GetVector3DMulMatrix44(const EVector3D& vec, const EMatrix44&mat, EVector3D &result)
	{
		EFloat x = vec.x * mat.m[0][0] + vec.y * mat.m[1][0] + vec.z * mat.m[2][0] + mat.m[3][0];
		EFloat y = vec.x * mat.m[0][1] + vec.y * mat.m[1][1] + vec.z * mat.m[2][1] + mat.m[3][1];
		EFloat z = vec.x * mat.m[0][2] + vec.y * mat.m[1][2] + vec.z * mat.m[2][2] + mat.m[3][2];

		result.x = x, result.y = y, result.z = z;
	}

	//--------------------------------------------------------------------------

	// 4D向量X44矩阵
	void GetVector4DMulMatrix44(const EVector4D& vec, const EMatrix44&mat, EVector4D &result)
	{
		EFloat x = vec.x * mat.m[0][0] + vec.y * mat.m[1][0] + vec.z * mat.m[2][0] + mat.m[3][0];
		EFloat y = vec.x * mat.m[0][1] + vec.y * mat.m[1][1] + vec.z * mat.m[2][1] + mat.m[3][1];
		EFloat z = vec.x * mat.m[0][2] + vec.y * mat.m[1][2] + vec.z * mat.m[2][2] + mat.m[3][2];
		
		result.x = x, result.y = y, result.z = z, result.w = 1;
	}

	//--------------------------------------------------------------------------

	void GetVertex4DMulMatrix44(const EVertex4D& vec, const EMatrix44&mat, EVertex4D &result)
	{
		// 变换顶点
		EFloat x = vec.x * mat.m[0][0] + vec.y * mat.m[1][0] + vec.z * mat.m[2][0] + mat.m[3][0];
		EFloat y = vec.x * mat.m[0][1] + vec.y * mat.m[1][1] + vec.z * mat.m[2][1] + mat.m[3][1];
		EFloat z = vec.x * mat.m[0][2] + vec.y * mat.m[1][2] + vec.z * mat.m[2][2] + mat.m[3][2];
		EFloat w = 1;

		//// 变换法线
		//EFloat nx = vec.nx * mat.m[0][0] + vec.ny * mat.m[1][0] + vec.nz * mat.m[2][0] + mat.m[3][0];
		//EFloat ny = vec.nx * mat.m[0][1] + vec.ny * mat.m[1][1] + vec.nz * mat.m[2][1] + mat.m[3][1];
		//EFloat nz = vec.nx * mat.m[0][2] + vec.ny * mat.m[1][2] + vec.nz * mat.m[2][2] + mat.m[3][2];

		result.x  = x,	result.y = y,	result.z = z,	result.w = 1;
		//result.nx = nx,	result.ny = ny,	result.nz = nz;
	}	

	//--------------------------------------------------------------------------

	void GetVertex4DAddVector4D(const EVertex4D &v, const EVector4D& p, EVertex4D &result)
	{
		// 定点变换
		EFloat x  = v.x + p.x;
		EFloat y  = v.y + p.y;
		EFloat z  = v.z + p.z;
		
		//// 法线变换
		//EFloat nx = v.nx + p.x;
		//EFloat ny = v.ny + p.y;
		//EFloat nz = v.nz + p.z;

		result.x = x, result.y = y, result.z = z, result.w  = 1;
	}

	//--------------------------------------------------------------------------

}